Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

nice_things/collections/List.sh

This page documents several modules related to Lists.

The List pseudo-class is not a real class. These modules are named as if they were members of a class just for organization and easier maintenance.

Data is stored in a simple variable using the shell's standard way of representing lists: a text string using the value of the IFS variable as the internal field separator. This means Lists are unsafe to expand and lossy. They cannot contain every possible string value (notably, they cannot contain other Lists.) For that reason, Lists should only be used in strict_mode, which alleviates the issues by setting IFS to a single, rarely-used control character, and makes Lists safe to expand by disabling pathname expansion (AKA globbing).

Note

If you need a lossless way to save a list, consider using an Array object instead. Arrays can also represent matrices, since they can contain objects, including other Arrays. But, being objects, they are harder to work with and have higher performance cost.

As is common in sh, indexing starts from 1, and go up to length inclusive. Functions that take an index argument also accept negative numbers to search from the end of the List.

List functions are generic over their arguments; they use standard positional parameters. This means not only Lists can be passed as argument, but any values in any way an arguments list can be created. For that reason, Lists must be expanded unquoted when passed as argument to these functions, to expand one argument for each item in the List. That is why push and concat functions are not needed. You can add items to a list or concatenate many lists in the same way it is done for strings, by just expanding them near each other:

# Create a list: letters=[a,b]
list letters a b
# Add items to the list: letters=[a,b,c,d]
list letters ${letters} c d
# Create another list: more_letters=[e,f]
list more_letters e f
# Concatenate 2 lists: all_letters=[a,b,c,d,e,f]
list all_letters ${letters} ${more_letters}

list

Since 0.3.0 · Source

import "{ list }" from nice_things/collections/List.sh

Synopsis
list <out_var> <item>…

Configuration

Description
Turn arguments into a list of items separated by IFS. When IFS contains more than one character, the first character of IFS is used as field-separator.

Lists are single-level. It is not possible to create a list of lists.

Lists are meant to be used in strict_mode. Without strict_mode this list format is unreliable due to accidental pathname expansions and IFS-splitting.

Options

Operands

  • <out_var>: Output variable; the result will be written to this variable.
  • <item>: An item to be added to the List.

Stdin

Stdout

Stderr
log_error.

Exit status

  • 0: Successful completion.
  • 18: IFS is null (abort).
  • 19: Invalid operand; list items cannot be lists.

Abort
Aborts if IFS is null.

Usage examples

list letters a b c d e
for letter in $letters; do
	printf 'The letter is: %s\n' "$letter"
done

contains

Since 0.3.0 · Source

import "{ contains }" from nice_things/collections/List_contains.sh

Synopsis
contains <item> <list>…

Configuration

Description
Test if <item> is contained in the List. Return status code 0 if true, 1 if false.

Options

Operands

  • <item>: The value to search.
  • <list>: An unquoted List.

Stdin

Stdout

Stderr

Exit status

  • 0: <item> is contained in the List.
  • 1: <item> is not contained in the List.

Abort

Usage examples

if contains d a b c d e; then
	printf '"d" is contained\n'
fi

fmt

Since 0.3.0 · Source

import "{ fmt }" from nice_things/collections/List_fmt.sh

Synopsis
fmt <out_var> <pattern> <list>…

Configuration

Description
Use a printf-style pattern to format each argument, return a List separated by IFS.

Compared to just using printf, this function does not print the <pattern> when the List is empty.

Options

Operands

  • <out_var>: Output variable; the result will be written to this variable.
  • <pattern>: A printf-style format pattern.
  • <list>: An unquoted List.

Stdin

Stdout

Stderr
log_error.

Exit status

  • 0: Successful completion.
  • 18: IFS is null (abort).

Abort
Aborts if IFS is null.

Usage examples

fmt objects './build/%s.o' main mod
printf '%s\n' $objects # ./build/main.o ./build/mod.o

list_from

Since 0.3.0 · Source

import "{ list_from }" from nice_things/collections/List_from.sh

Synopsis
list_from <out_var> <string> [<separator>]

Configuration

Description
Turn <string> into a List splitting at each occurrence of separator. If <separator> is not provided the default value of IFS is used (space, tab, line-feed).

Options

Operands

  • <out_var>: Output variable; the result will be written to this variable.
  • <string>: The text string to split.
  • <separator>: One or more characters to be used as field-separator.

Stdin

Stdout

Stderr

Exit status

  • 0: Successful completion.
  • 18: IFS is null (abort).
  • 19: Invalid operand; list items cannot be lists.

Abort
Aborts if IFS is null.

Usage examples

csv="a,b,c,d,e"
list_from fields "$csv" ","

get

Since 0.3.0 · Source

import "{ get }" from nice_things/collections/List_get.sh

Synopsis
get <out_var> <index> <list>…

Configuration

Description
Get an item from a List by index.

<index> starts from 1 and go to the length of the List inclusive.

Negative <index> can be used to count from the end of the List, where -1 retrieves the last item, and -length the first.

This function does not check if <index> is within bounds. The behavior when trying to get an index that does not exist in the List is dependent on if strict_mode is in use, in which case the set -u (nounset) configuration should cause it to abort with a shell-dependent error code.

Options

Operands

  • <out_var>: Output variable; the result will be written to this variable.
  • <index>: Index of the item to retrieve starting from 1.
  • <list>: An unquoted List.

Stdin

Stdout

Stderr

Exit status

  • 0: Successful completion.

Abort
Some shells may abort in strict_mode if <index> is out-of-bounds.

Usage examples

get letter 3 a b c d e
printf '%s\n' "$letter" # c

is_list

Since 0.3.0 · Source

import "{ is_list }" from nice_things/collections/List_is_list.sh

Synopsis
is_list <arg>…

Configuration

Description
Test if any of the arguments is itself a List according to the current value of IFS.

Options

Operands
<arg>: Any string.

Stdin

Stdout

Stderr

Exit status

  • 0: One or more of the arguments is a List.
  • 1: None of the arguments is a List.

Abort

Usage examples

if is_list "$@"; then
	printf 'Some argument contains an IFS character\n'
fi

length

Since 0.3.0 · Source

import "{ length }" from nice_things/collections/List_length.sh

Synopsis
length <out_var> <list>…

Configuration

Description
Get the length of a List.

The <list> operand should be expanded unquoted as this function returns the length of the positional parameters list.

Options

Operands

  • <out_var>: Output variable; the result will be written to this variable.
  • <list>: An unquoted List.

Stdin

Stdout

Stderr

Exit status
0: Successful completion.

Abort

Usage examples

length len a b c d e
printf '%s\n' "$len" # 5

to_string

Since 0.3.0 · Source

import "{ to_string }" from nice_things/collections/List_to_string.sh

Synopsis
to_string <list>…

Configuration

Description
Print a human-readable string representation of a List.

The output of this function is for debug purposes only. This is not a reversible serialization of the list, and the format is not standardized and can change.

Options

Operands
<list>: An unquoted List.

Stdin

Stdout
A human-readable representation of a List.

Stderr

Exit status
0: Successful completion.

Abort

Usage examples

log_debug "Positional parameters: $(to_string "$@")"

readonly:list_is_terminated

Since 0.3.0 · Source

import "{ readonly:list_is_terminated }" from nice_things/collections/List_is_terminated.sh

Synopsis
[ -n "$list_is_terminated" ]

Configuration

Description
Will be set to 1 if List should have a terminating field separator in the current shell. Will be null otherwise.

This readonly variable is used internally by the list functions to decide if a trailing field separator should be printed. It was created specifically for zsh, which differs from all other shells by not accepting a terminating field separator. This behavior makes List slightly less robust in zsh, since it cannot differentiate an empty List from a List containing a single null value.

Options

Operands

Stdin

Stdout

Stderr
log_error.

Exit status

  • 0: Successful definition.
  • 13: Unexpected error (on initialization) (abort).

Abort
Aborts if initialization fails.

Usage examples

if [ -n "$list_is_terminated" ]; then
	printf '%s' "${IFS%"${IFS#?}"}"
fi